package edu.pku.sei.transformation.editor.model;

import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.queryscript.parser.ScriptParser;
import edu.pku.sei.queryscript.parser.Ast.Ast;
import edu.pku.sei.transformation.editor.model.variable.Variable;

public class Expression extends MetaModelElement {
	private boolean alreadyBinded = false;
	// private boolean bindSuccess = true;
	private String exp = "";
	private Ast syntaxTree = null;
	private MetaModelElement context;

	public Object getContext() {
		return context;
	}

	public void setContext(MetaModelElement context) {
		this.context = context;
	}

	public Ast getSyntaxTree() {
		return syntaxTree;
	}

	@MethodProperty(name = "expression", catalog = "expression", id = ModelPackage.EXPRESSION_EXP, setter = "setExp")
	public String getExp() {
		return exp;
	}

	public void setExp(String exp) {
		String oldValue = this.exp;
		if (oldValue == null || !oldValue.equals(exp)) {
			this.exp = exp;
			syntaxTree = ScriptParser.parse(exp);
			alreadyBinded = false;
			// this.bind();
			this.firePropertyChange(ModelPackage.EXPRESSION_EXP, oldValue, exp);
			if (this.container != null)
				this.container.firePropertyChange(ModelPackage.EXPRESSION_EXP,
						oldValue, exp);
		}
	}

	@Override
	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeAttribute(root,
				ModelPackage.EXPRESSION_EXP, this.exp);
		XMLUtility.xmlInstance.serializeNodeNotContain(root,
				ModelPackage.EXPRESSION_CONTEXT, context);
	}

	@Override
	public void deSerialize(Element root) {
		super.deSerialize(root);
		this.exp = XMLUtility.xmlInstance.deSerializeString(root,
				ModelPackage.EXPRESSION_EXP);
		this.context = (MetaModelElement) XMLUtility.xmlInstance
				.deSerializeNodeNotContain(root,
						ModelPackage.EXPRESSION_CONTEXT, this);
		syntaxTree = ScriptParser.parse(exp);
	}

	@Override
	public void dynamicSet(String featureID, Object value) {
		if (ModelPackage.EXPRESSION_CONTEXT.equals(featureID)) {
			this.context = (MetaModelElement) value;
		} else
			super.dynamicSet(featureID, value);
	}

	@Override
	public String toString() {
		if (exp != null)
			return exp;
		return super.toString();
	}

	public void bind() {
		if (!alreadyBinded && syntaxTree != null) {
			// syntaxTree.bind(context);
			alreadyBinded = true;
		}
	}

	public void resetAlreadyBinded() {
		alreadyBinded = false;
	}

	public void removeBinding(Variable v) {
		if (syntaxTree != null) {
			// syntaxTree.removeInvalidBinding();
		}

	}
}
